package com.jeomo.sys.provider.sysoption;

import com.jeomo.sys.provider.sysoption.mapper.SysOptionMapper;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;

/**
 * 系统选项
 *
 * @author:Jackpot
 * @create 2020-12-08 12:00
 * @description:
 */
public abstract class BaseSysOption{

    @Resource
    private SysOptionMapper sysOptionMapper;

    /**
     * 读取系统选项配置到实体字段中
     */
    public final void load() {
        Field[] fields = getClass().getDeclaredFields();
        int length = fields.length;
        if (length == 0) {
            throw new SysOptionException("系统选项声明的属性不能为空!");
        }
        SysOption sysOption = sysOptionMapper.selectById(getCode(getClass()));
        if (sysOption== null) return;
        String data = sysOption.getData();
        try {
            JSONObject jsonObj = new JSONObject(data);
            for (int i = 0; i < length; i++) {
                Field field = fields[i];
                field.setAccessible(true);
                handleField(field, jsonObj);
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    private void handleField(Field field, JSONObject jsonObj) {
        OptionField optionField = field.getDeclaredAnnotation(OptionField.class);
        if (optionField == null) return;
        OptionType type = optionField.type();
        Object value = jsonObj.opt(field.getName());
        if (value == null) return;
        switch (type) {
            case STRING_TYPE:
                value = jsonObj.optString(field.getName());
                break;
            case INT_TYPE:
                value = jsonObj.optInt(field.getName());
                break;
            case LONG_TYPE:
                value = jsonObj.optLong(field.getName());
                break;
            case DATE_TYPE:
                String dateStr = jsonObj.optString(field.getName());
                value = LocalDate.parse(dateStr);
                break;
            case TIME_TYPE:
                String timeStr = jsonObj.optString(field.getName());
                value = LocalTime.parse(timeStr);
                break;
            case DATE_TIME_TYPE:
                String dateTimeStr = jsonObj.optString(field.getName());
                value = LocalDateTime.parse(dateTimeStr);
                break;
            case BOOL_TYPE:
                value = jsonObj.optBoolean(field.getName());
                break;
            case FLOAT_TYPE:
                value = Float.parseFloat(jsonObj.optString(field.getName()));
                break;
            case DOUBLE_TYPE:
                value = jsonObj.optDouble(field.getName());
                break;
            case STRING_LIST_TYPE:
                String jsonArrStr = jsonObj.optString(field.getName());
                value = jsonArrayToList(new JSONArray(jsonArrStr));
                break;
            default:
                throw new SysOptionException("不支持的数据类型!");
        }
        try {
            field.set(this, value);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    private List<String> jsonArrayToList(JSONArray jsonArray){
        if (jsonArray==null || jsonArray.length() == 0) return null;
        List<String> strings = new ArrayList<>();
        for (int i = 0; i < jsonArray.length() ; i++) {
            strings.add(jsonArray.optString(i));
        }
        return strings;
    }

    public final boolean save(){
        Field[] fields = getClass().getDeclaredFields();
        int length = fields.length;
        if (length == 0) {
            throw new SysOptionException("系统选项声明的属性不能为空!");
        }

        JSONObject jsonObj = new JSONObject();
        for (int i = 0; i < length; i++) {
            Field field = fields[i];
            field.setAccessible(true);
            fieldValueToJson(field,jsonObj);
        }
        String jsonStr = jsonObj.toString();
        SysOption sysOption = new SysOption();

        Class<? extends BaseSysOption> clazz = getClass();
        sysOption.setCode(getCode(clazz));
        sysOption.setName(getName(clazz));
        sysOption.setData(jsonStr);
        sysOption.setGroupCode(getGroup());
        sysOption.setGroupName(getGroupName());
        int delete = sysOptionMapper.deleteById(getCode(clazz));
        int insert = sysOptionMapper.insert(sysOption);
        return delete+insert >0 ?true:false;
    }

    protected String getCode(Class<? extends BaseSysOption> clazz){
        String code = null;
        SystemOption systemOption = clazz.getDeclaredAnnotation(SystemOption.class);
        if (systemOption != null && systemOption.code().length()!=0) {
            code = systemOption.code();
        }else {
            code = clazz.getSimpleName();
        }
        return code;
    }
    protected String getName(Class<? extends BaseSysOption> clazz){
        String name = null;
        SystemOption systemOption = clazz.getDeclaredAnnotation(SystemOption.class);
        if (systemOption != null && systemOption.name().length()!=0) {
            name = systemOption.name();
        }
        return name;
    }

    private String fieldValueToJson(Field field, JSONObject jsonObj){
        OptionField optionField = field.getDeclaredAnnotation(OptionField.class);
        if (optionField == null) return null;
        OptionType type = optionField.type();
        String str = null;
        Object value = null;
        try {
            value = field.get(this);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        if (value == null) return null;
        switch (type) {
            case STRING_TYPE:
                str = value.toString();
                break;
            case INT_TYPE:
                str = value.toString();
                break;
            case LONG_TYPE:
                str = value.toString();
                break;
            case DATE_TYPE:
                LocalDate localDate = (LocalDate) value;
                str = localDate.format(DateTimeFormatter.ISO_LOCAL_DATE);
                break;
            case TIME_TYPE:
                LocalTime localTime = (LocalTime) value;
                str = localTime.format(DateTimeFormatter.ISO_LOCAL_TIME);
                break;
            case DATE_TIME_TYPE:
                LocalDateTime localDateTime = (LocalDateTime) value;
                str = localDateTime.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
                break;
            case BOOL_TYPE:
                str = value.toString();
                break;
            case FLOAT_TYPE:
                str = value.toString();
                break;
            case DOUBLE_TYPE:
                str = value.toString();
                break;
            case STRING_LIST_TYPE:
                List<String> strings = (List<String>) value;
                JSONArray jsonArray = new JSONArray((List<String>) value);
                str = jsonArray.toString();
                break;
            default:
                throw new SysOptionException("不支持的数据类型!");
        }
        try {
            jsonObj.putOpt(field.getName(), str);
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return str;
    }


    /**
     * 选项分组标识
     * @return
     */
    public String getGroup(){
        return null;
    }
    /**
     * 选项分组名称
     * @return
     */
    public String getGroupName(){
        return null;
    }
}
